<template>
  <div id="main">
    <div class="text">{{text}}</div>
    <video id="video" playsinline style="
      width: auto;
      height: auto;
     -webkit-transform: scaleX(-1);
      transform: scaleX(-1);
      ">
    </video>
    <canvas id="output"></canvas>
  </div>
</template>

<script>
let model, ctx, videoWidth, videoHeight, video, canvas;
import { loadMobileNet } from "@/api/loadModel";
export default {
  props: {
    width: {
      type: Number,
      default: 240,
    },
    height: {
      type: Number,
      default: 240,
    },
  },
  data() {
    return {
      text: "",
    };
  },
  async mounted() {
    await this.setupCamera();
    await this.setupPage();
  },
  methods: {
    async setupCamera() {
      let vm = this;
      let video = document.getElementById("video");
      const stream = await navigator.mediaDevices.getUserMedia({
        audio: false,
        video: {
          facingMode: "user",
          width: vm.width,
          height: vm.height,
        },
      });
      video.srcObject = stream;
      return new Promise((resolve) => {
        video.onloadedmetadata = () => {
          resolve(video);
        };
      });
    },
    async setupPage() {
      let vm = this;
      await vm.tf.setBackend("cpu");
      await this.setupCamera();
      let video = document.getElementById("video");
      video.play();
      video.width = vm.width;
      video.height = vm.height;
      canvas = document.getElementById("output");
      canvas.width = vm.width;
      canvas.height = vm.height;
      ctx = canvas.getContext("2d");
      ctx.fillStyle = "rgba(255, 0, 0, 0.5)";
      model = await loadMobileNet();
      setInterval(() => {
        vm.renderPrediction(video);
      }, 60);
    },
    async renderPrediction(video) {
      let vm = this;
      const returnTensors = false;
      const flipHorizontal = true;
      const annotateBoxes = true;
      const predictions = await model.estimateFaces(
        video,
        returnTensors,
        flipHorizontal,
        annotateBoxes
      );
      if (predictions.length > 0) {
        ctx.clearRect(0, 0, vm.width, vm.height);
        for (let i = 0; i < predictions.length; i++) {
          if (returnTensors) {
            predictions[i].topLeft = predictions[i].topLeft.arraySync();
            predictions[i].bottomRight = predictions[i].bottomRight.arraySync();
            if (annotateBoxes) {
              predictions[i].landmarks = predictions[i].landmarks.arraySync();
            }
          }
          const start = predictions[i].topLeft;
          const end = predictions[i].bottomRight;
          const size = [end[0] - start[0], end[1] - start[1]];
          ctx.fillStyle = "rgba(255, 0, 0, 0.5)";
          ctx.fillRect(start[0], start[1], size[0], size[1]);
          if (annotateBoxes) {
            const landmarks = predictions[i].landmarks;
            // 左眼到鼻子比值
            //右眼到鼻子比例
            const lefteyex = landmarks[1][0];
            const righteyex = landmarks[0][0];
            const nosex = landmarks[2][0];
            const lefteyetonosex = Math.abs(lefteyex - nosex);
            const lrighteyetonosex = Math.abs(righteyex - nosex);

            const lefteyey = landmarks[1][1];
            const righteyey = landmarks[0][1];
            const eyeaverY = (lefteyey + righteyey) / 2;
            const noseY = landmarks[2][1];
            const leftear = landmarks[5][1];
            const rightear = landmarks[4][1];
            const earaverY = (leftear + rightear) / 2;
            if (Math.abs(lefteyetonosex - lrighteyetonosex) > 5) {
              vm.text = "请正脸面对";
            } else if (eyeaverY > earaverY) {
              vm.text = "请抬头";
            } else if (noseY < earaverY) {
              vm.text = "请低头";
            } else {
              vm.text = "";
            }
            ctx.fillStyle = "blue";
            for (let j = 0; j < landmarks.length; j++) {
              const x = landmarks[j][0];
              const y = landmarks[j][1];
              ctx.fillRect(x, y, 5, 5);
            }
          }
        }
      } else {
        vm.text = "未检测到人脸";
      }
    },
  },
};
</script>

<style>
#main {
  position: relative;
  margin: 50px 0;
  height: 100vh;
}

canvas {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  margin: auto;
  border-radius: 50%;
}
video {
  border-radius: 50%;
}
.text {
  position: fixed;
  z-index: 100;
  width: 100%;
  height: 50px;
  line-height: 50px;
  text-align: center;
  top: 900px;
  font-size: 50px;
  color: blue;
}

#description {
  margin-top: 20px;
  width: 600px;
}

#description-title {
  font-weight: bold;
  font-size: 18px;
}
</style>